//
//  TouchGestITTest.m
//  TouchGestITTest
//
//  Created by Davide Spano on 28/08/12.
//  Copyright (c) 2012 Davide Spano. All rights reserved.
//

#import "TouchGestITTest.h"
#import "SimpleTmpExp.h"
#import "BinaryTmpExp.h"
#import "ComplexTmpExp.h"
#import "TouchContent.h"
#import "TouchToken.h"
#import "TouchEventArgs.h"
#import "Emitter.h"
@implementation TouchGestITTest

- (void)setUp
{
    [super setUp];
    
    // Set-up code here.
}

- (void)tearDown
{
    // Tear-down code here.
    
    [super tearDown];
}

- (void)testMethod1
{
    SimpleTmpExp* touchStart = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchMove = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    touchMove.iterative = true;
    SimpleTmpExp* touchEnd = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    
    BinaryTmpExp* b1 = [[BinaryTmpExp alloc] initWithOperands:touchMove :touchEnd :Disabling];
    BinaryTmpExp* pan = [[BinaryTmpExp alloc] initWithOperands:touchStart :b1 :Enabling];
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:pan];
    
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];
    
    STAssertEquals(Completed, pan.state, @"error on gesture recognition");
    
}

- (void) testMethod2
{
    // this method tests the correct interpretation of a pinch gesture
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchStart2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    SimpleTmpExp* touchMove2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :2]];
    touchMove1.iterative = true;
    touchMove2.iterative = true;
    
    SimpleTmpExp* touchEnd1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    SimpleTmpExp* touchEnd2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :2]];
    
    ComplexTmpExp* start = [[ComplexTmpExp alloc] init];
    start.tmpOperator = OrderIndependence;
    [start addOperand:touchStart1];
    [start addOperand:touchStart2];
    
    BinaryTmpExp* move = [[BinaryTmpExp alloc] initWithOperands:touchMove1 :touchMove2 :Parallel];
    
    ComplexTmpExp* end = [[ComplexTmpExp alloc] init];
    end.tmpOperator = OrderIndependence;
    [end addOperand:touchEnd1];
    [end addOperand:touchEnd2];
    
    BinaryTmpExp* b1 = [[BinaryTmpExp alloc] initWithOperands:move :end :Disabling];
    BinaryTmpExp* pinch = [[BinaryTmpExp alloc] initWithOperands:start :b1 :Enabling];
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:pinch];
    
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :2 :Start]];
    STAssertEquals(Completed, start.state, @"error on gesture recognition");
    
    STAssertEquals(Enabled, touchMove1.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchMove2.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    STAssertEquals(Enabled, touchMove1.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchMove2.state, @"error on gesture recognition");
    STAssertEquals(Performing, pinch.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    STAssertEquals(Performing, pinch.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :End]];
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];
    
    STAssertEquals(Completed, pinch.state, @"error on gesture recognition");
}

- (void) testMethod3{
    // declare a pan
    SimpleTmpExp* touchStart = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchMove  = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    touchMove.iterative = true;
    SimpleTmpExp* touchEnd = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    BinaryTmpExp* b1 = [[BinaryTmpExp alloc] initWithOperands:touchMove :touchEnd :Disabling];
    BinaryTmpExp* pan = [[BinaryTmpExp alloc] initWithOperands:touchStart :b1 :Enabling];
    
    
    // declare a pinch
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchStart2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    SimpleTmpExp* touchMove2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :2]];
    touchMove1.iterative = true;
    touchMove2.iterative = true;
    
    SimpleTmpExp* touchEnd1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    SimpleTmpExp* touchEnd2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :2]];
    
    ComplexTmpExp* start = [[ComplexTmpExp alloc] init];
    start.tmpOperator = OrderIndependence;
    [start addOperand:touchStart1];
    [start addOperand:touchStart2];
    
    BinaryTmpExp* move = [[BinaryTmpExp alloc] initWithOperands:touchMove1 :touchMove2 :Parallel];
    
    ComplexTmpExp* end = [[ComplexTmpExp alloc] init];
    end.tmpOperator = OrderIndependence;
    [end addOperand:touchEnd1];
    [end addOperand:touchEnd2];
    
    BinaryTmpExp* b2 = [[BinaryTmpExp alloc] initWithOperands:move :end :Disabling];
    BinaryTmpExp* pinch = [[BinaryTmpExp alloc] initWithOperands:start :b2 :Enabling];
    
    // declare the whole gesture
    BinaryTmpExp* gesture = [[BinaryTmpExp alloc] initWithOperands:pan :pinch :Choice];

    Emitter* touchEmitter = [[Emitter alloc] init];
    gesture.iterative = true;
    [touchEmitter setGestureDescription:gesture];
    
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    
    STAssertEquals(Enabled, pan.state, @"error on gesture recognition");
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Performing, pan.state, @"error on gesture recognition");
    STAssertEquals(Performing, pinch.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :2 :Start]];
    STAssertEquals(Completed, start.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    STAssertEquals(Disabled, pan.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchMove1.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchMove2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchEnd2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchEnd1.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    STAssertEquals(Enabled, touchEnd2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchEnd1.state, @"error on gesture recognition");

    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    STAssertEquals(Enabled, touchEnd2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchEnd1.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    
    STAssertEquals(Enabled, touchEnd2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchEnd1.state, @"error on gesture recognition");

    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :End]];
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Performing, end.state, @"error on gesture recognition");
    STAssertEquals(Completed, touchEnd2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchEnd1.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];
    
    STAssertEquals(Enabled, gesture.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];

     STAssertEquals(Enabled, gesture.state, @"error on gesture recognition");
}

- (void) testMethod4{
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc]initWithTypeId:Start :1]];
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc]initWithTypeId:Move :1]];
    
    BinaryTmpExp* bexp1 = [[BinaryTmpExp alloc] initWithOperands:touchStart1 :touchMove1 :Enabling];
    bexp1.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:bexp1];
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Completed, touchStart1.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    STAssertEquals(Completed, touchMove1.state, @"error on gesture recognition");
    STAssertEquals(Enabled, bexp1.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchStart1.state, @"error on gesture recognition");
}

- (void) testMethod5{
    SimpleTmpExp* touchStart = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    touchStart.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    
    [touchEmitter setGestureDescription:touchStart];
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Move]];
    STAssertEquals(Enabled, touchStart.state, @"error on gesture recognition");
}

- (void) testMethod6{
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    BinaryTmpExp* bexp1 = [[BinaryTmpExp alloc] initWithOperands:touchStart1 :touchMove1 :Enabling];
    bexp1.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:bexp1];
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Move]];
    STAssertEquals(Enabled, touchStart1.state, @"error on gesture recognition");
    STAssertNotNil(touchStart1.token, @"error on gesture recognition");
    
}

- (void) testMethod7{
    SimpleTmpExp* openHand = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* openHand2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    openHand2.iterative = true;
    SimpleTmpExp* grab = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    BinaryTmpExp* bexp1 = [[BinaryTmpExp alloc] initWithOperands:openHand2 :grab :Disabling];
    BinaryTmpExp* bexp3 = [[BinaryTmpExp alloc] initWithOperands:openHand :bexp1 :Enabling];
    
    SimpleTmpExp* move = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    move.iterative = true;
    
    SimpleTmpExp* release = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    BinaryTmpExp* bexp2 = [[BinaryTmpExp alloc] initWithOperands:move :release :Disabling];
    
    BinaryTmpExp* gesture = [[BinaryTmpExp alloc] initWithOperands:bexp3 :bexp2 :Enabling];
    gesture.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:gesture];
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Enabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Enabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Enabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Enabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Enabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :2 :Start]];
    STAssertEquals(Disabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Completed, grab.state, @"error on gesture recognition");
    STAssertEquals(Enabled, move.state, @"error on gesture recognition");
    STAssertEquals(Enabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Move]];
    STAssertEquals(Disabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Disabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Enabled, move.state, @"error on gesture recognition");
    STAssertEquals(Enabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Move]];
    STAssertEquals(Disabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Disabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Enabled, move.state, @"error on gesture recognition");
    STAssertEquals(Enabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Move]];
    STAssertEquals(Disabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Disabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Enabled, move.state, @"error on gesture recognition");
    STAssertEquals(Enabled, release.state, @"error on gesture recognition");
    STAssertEquals(Performing, gesture.state, @"error on gesture recognition");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :End]];
    STAssertEquals(Enabled, gesture.state, @"error on gesture recognition");
    
}

- (void) testMethod8{
    SimpleTmpExp* openHand = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* openHand2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    openHand2.iterative = true;
    SimpleTmpExp* grab = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    BinaryTmpExp* bexp1 = [[BinaryTmpExp alloc] initWithOperands:openHand2 :grab :Disabling];
    BinaryTmpExp* bexp3 = [[BinaryTmpExp alloc] initWithOperands:openHand :bexp1 :Enabling];
    
    SimpleTmpExp* move = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    move.iterative = true;
    
    SimpleTmpExp* release = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    BinaryTmpExp* bexp2 = [[BinaryTmpExp alloc] initWithOperands:move :release :Disabling];
    
    BinaryTmpExp* gesture = [[BinaryTmpExp alloc] initWithOperands:bexp3 :bexp2 :Enabling];
    gesture.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:gesture];
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    STAssertEquals(Enabled, openHand.state, @"error on gesture recognition");
    STAssertEquals(Disabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Disabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Move]];
    STAssertEquals(Enabled, openHand.state, @"error on gesture recognition");
    STAssertEquals(Disabled, openHand2.state, @"error on gesture recognition");
    STAssertEquals(Disabled, grab.state, @"error on gesture recognition");
    STAssertEquals(Disabled, move.state, @"error on gesture recognition");
    STAssertEquals(Disabled, release.state, @"error on gesture recognition");
    STAssertEquals(Enabled, gesture.state, @"error on gesture recognition");
    
    
    
}

-(void) testMethod9{
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchStart2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    SimpleTmpExp* touchMove2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :2]];
    touchMove1.iterative = true;
    touchMove2.iterative = true;
    
    SimpleTmpExp* touchEnd1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    SimpleTmpExp* touchEnd2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :2]];
    
    ComplexTmpExp* start = [[ComplexTmpExp alloc] init];
    start.tmpOperator = OrderIndependence;
    [start addOperand:touchStart1];
    [start addOperand:touchStart2];
    
    BinaryTmpExp* move = [[BinaryTmpExp alloc] initWithOperands:touchMove1 :touchMove2 :Parallel];
    
    ComplexTmpExp* end = [[ComplexTmpExp alloc] init];
    end.tmpOperator = OrderIndependence;
    [end addOperand:touchEnd1];
    [end addOperand:touchEnd2];
    
    BinaryTmpExp* b1 = [[BinaryTmpExp alloc] initWithOperands:move :end :Disabling];
    BinaryTmpExp* pinch = [[BinaryTmpExp alloc] initWithOperands:start :b1 :Enabling];
    pinch.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:pinch];
    
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    // simulate a recognition error
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    // at this time, the gesture should restart
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :2 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :End]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];
    
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");

    
}

- (void) testMethod10
{
    // this method tests the correct propagation of the errors in a pinch gesture
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchStart2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    SimpleTmpExp* touchMove2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :2]];
    touchMove1.iterative = true;
    touchMove2.iterative = true;
    
    SimpleTmpExp* touchEnd1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    SimpleTmpExp* touchEnd2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :2]];
    
    ComplexTmpExp* start = [[ComplexTmpExp alloc] init];
    start.tmpOperator = OrderIndependence;
    [start addOperand:touchStart1];
    [start addOperand:touchStart2];
    
    BinaryTmpExp* move = [[BinaryTmpExp alloc] initWithOperands:touchMove1 :touchMove2 :Parallel];
    
    ComplexTmpExp* end = [[ComplexTmpExp alloc] init];
    end.tmpOperator = OrderIndependence;
    [end addOperand:touchEnd1];
    [end addOperand:touchEnd2];
    
    BinaryTmpExp* b1 = [[BinaryTmpExp alloc] initWithOperands:move :end :Disabling];
    BinaryTmpExp* pinch = [[BinaryTmpExp alloc] initWithOperands:start :b1 :Enabling];
    pinch.iterative = true;
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    [touchEmitter setGestureDescription:pinch];
    
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :2 :Start]];
    STAssertEquals(Completed, start.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :End]];
     NSLog(@"[Test 10] simulate error");
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];
    
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchStart1.state, @"error on gesture recognition");
    STAssertEquals(Enabled, touchStart2.state, @"error on gesture recognition");
    STAssertEquals(Enabled, start.state, @"error on gesture recognition");
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :2 :Start]];
    STAssertEquals(Completed, start.state, @"error on gesture recognition");
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :Move]];
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :2 :End]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];

    
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");
}

- (void) testMethod0{
    // declare a pan
    SimpleTmpExp* touchStart = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchMove  = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    touchMove.iterative = true;
    SimpleTmpExp* touchEnd = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    BinaryTmpExp* b1 = [[BinaryTmpExp alloc] initWithOperands:touchMove :touchEnd :Disabling];
    BinaryTmpExp* pan = [[BinaryTmpExp alloc] initWithOperands:touchStart :b1 :Enabling];
    
    
    // declare a pinch
    SimpleTmpExp* touchStart1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :1]];
    SimpleTmpExp* touchStart2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Start :2]];
    
    SimpleTmpExp* touchMove1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :1]];
    SimpleTmpExp* touchMove2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:Move :2]];
    touchMove1.iterative = true;
    touchMove2.iterative = true;
    
    SimpleTmpExp* touchEnd1 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :1]];
    SimpleTmpExp* touchEnd2 = [[SimpleTmpExp alloc] initWithContent:[[TouchContent alloc] initWithTypeId:End :2]];
    
    ComplexTmpExp* start = [[ComplexTmpExp alloc] init];
    start.tmpOperator = OrderIndependence;
    [start addOperand:touchStart1];
    [start addOperand:touchStart2];
    
    BinaryTmpExp* move = [[BinaryTmpExp alloc] initWithOperands:touchMove1 :touchMove2 :Parallel];
    
    ComplexTmpExp* end = [[ComplexTmpExp alloc] init];
    end.tmpOperator = OrderIndependence;
    [end addOperand:touchEnd1];
    [end addOperand:touchEnd2];
    
    BinaryTmpExp* b2 = [[BinaryTmpExp alloc] initWithOperands:move :end :Disabling];
    BinaryTmpExp* pinch = [[BinaryTmpExp alloc] initWithOperands:start :b2 :Enabling];
    
    // declare the whole gesture
    BinaryTmpExp* gesture = [[BinaryTmpExp alloc] initWithOperands:pan :pinch :Choice];
    
    Emitter* touchEmitter = [[Emitter alloc] init];
    gesture.iterative = true;
    [touchEmitter setGestureDescription:gesture];
    
    [touchEmitter startRecognition:[[TouchToken alloc] initWithTracking:Last]];
    
    
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:200.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:100.0 :100.0 :1 :Start]];
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");

    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :Move]];
    [touchEmitter feedDeviceEvent:[[TouchEventArgs alloc] initWithPointType:300.0 :200.0 :1 :End]];
    STAssertEquals(Enabled, pinch.state, @"error on gesture recognition");

}


@end
